Виджеты. Stack и Positioned
➡️Ссылка на репозиторий с кодом этого урока
Текст поверх Фонового Изображения
Очень частая задача - разместить текст или другие элементы поверх изображения. Stack идеально подходит для этого.
class StackExample3 extends StatelessWidget {
const StackExample3({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
// Ограничиваем размер Stack для примера
width: 350,
height: 350,
child: Stack(
children: <Widget>[
// Фоновое изображение (внизу Stack)
Image.asset(
'assets/images/student1.jpeg',
fit: BoxFit.contain, // Изображение покроет доступное пространство
width: double.infinity, // Растягиваем по ширине контейнера Stack
height: double.infinity, // Растягиваем по высоте контейнера Stack
),
Positioned(
bottom: 20, // Отступ 20 от нижнего края Stack
left: 20, // Отступ 20 от левого края Stack
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.black.withValues(alpha: 0.7),
),
child: Text(
'Flutter курс 2025',
style: TextStyle(
fontSize: 24,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
);
}
}

Создание Виджета "Бейдж" (Badge)
Это классический пример использования Stack и Positioned для создания наложения. Бейдж — это обычно небольшой значок (например, с числом уведомлений), расположенный поверх другого элемента (например, аватара или иконки).
Очень частая задача: показать количество уведомлений рядом с аватаром или иконкой. Stack и Positioned идеально подходят для этого!
class StackExample4 extends StatelessWidget {
const StackExample4({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Card(
color: Colors.yellow[100],
margin: EdgeInsets.all(20.0),
elevation: 1,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// Контейнер Stack для аватара и бейджа
Stack(
clipBehavior: Clip.none, // Позволяет бейджу выходить за границы аватара
children: <Widget>[
CircleAvatar(
radius: 30,
backgroundImage: AssetImage(
'assets/images/student2.png',
),
),
// Бейдж (позиционирован относительно аватара через Stack)
Positioned(
top: -5, // Сдвигаем немного вверх от верхнего края Stack (аватара)
right: -5, // Сдвигаем немного вправо от правого края Stack (аватара)
child: Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.red, // Красный фон бейджа
shape: BoxShape.circle, // Круглая форма
),
constraints: BoxConstraints(
minWidth: 20,
minHeight: 20,
),
child: Center(
child: Text(
'5',
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
SizedBox(width: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Имя пользователя",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
Text(
"Онлайн",
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
),
],
),
],
),
),
),
);
}
}

/
